﻿
using CNative.WebApi.Common;
using CNative.WebApi.Utils;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace CNative.WebApi.ServiceProcess
{
    public class BootstrapBase : IBootstrap
    {
        #region Bootstrap
        public BootstrapBase(string serviceName, string description, IConfigBase _configBase)
        {
            ServiceName = serviceName;
            Description = description;
            configBase = _configBase;
            configBase.ConfigFileChanged = ConfigFileChanged;
        }
        #endregion

        #region 变量
        public string ServiceName
        {
            get;
            set;
        }
        public string Description
        {
            get;
            set;
        }
        protected System.Threading.Timer timer = null;
        protected IConfigBase configBase = null;
        public IConfigBase ConfigBase
        {
            get { return configBase; }
            set { configBase = value; }
        }

        public string BaseDirectory
        {
            get
            {
                //string location = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.LastIndexOf('\\'));
                return CNative.WebApi.Common.ConfigBase.BaseDirectory ;
            }
        }
        #endregion

        #region Start/Stop
        public virtual void Start()
        {
            try
            {
                LogUtil.Info(this.Description + ",已启动");

                Init();
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        }
        /// <summary>
        /// 停止此服务。
        /// </summary>
        public virtual void Stop()
        {
            try
            {
                timer.Dispose();
                LogUtil.Info(this.Description + ",已停止");
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        }
        #endregion

        #region Init
        /// <summary>
        /// Init
        /// </summary>
        protected virtual void Init()
        {
            try
            {
                timer = new System.Threading.Timer(new System.Threading.TimerCallback(timer1_Tick), null, 5000, 1000);
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        } 
        protected virtual void  ConfigFileChanged()
        {
            try
            {
                
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        }
        private void Timertask_ExceptionMessageEvent(string ErrMessage)
        {
            LogUtil.Error(ErrMessage);
        }
        #endregion

        #region timerTick
        protected bool IsFirtRun = true;
        string str = "Run Time：{0}days {1:00}:{2:00}:{3:00} \nConfig Info: {4}";
        protected System.DateTime dtStartTime = System.DateTime.Now;
        protected int Timers = 0;
        protected virtual void timer1_Tick(object sender)
        {
            try
            {
                if (IsFirtRun)
                {
                    IsFirtRun = false;
                    dtStartTime = System.DateTime.Now;
                    //WatcherStrart(configBase.GetAppSettings("FileWatcherFilter", "*.dll"));
                    ShowConfigInfo();
                    //AutoUpdate(true);                    
                }
                System.TimeSpan ts = System.DateTime.Now - dtStartTime;
                if (ts.Seconds == 0)
                {
                    //AutoUpdate(false);
                    if (configBase.WatchConfig())
                        ShowConfigInfo();
                }
                if (ts.Minutes == 0 && ts.Seconds == 0)
                {                    
                    LogUtil.Info(string.Format(str, ts.Days, ts.Hours, ts.Minutes, ts.Seconds,
                         "TimeType=" + configBase.TimeType
                        + ",IntervalTime=" + configBase.IntervalTime)
                        );
                }
                this.timerTick(ts);
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        }
        
        protected bool isCalling = false;
        protected virtual void timerTick(System.TimeSpan ts)
        {
            try
            {
                if (configBase.IntervalTime > 0 && Timers >= configBase.IntervalTime)
                {
                    Timers = 0;
                    if (isCalling == false)
                    {
                        isCalling = true;
                        timerCall();
                    }
                }
                if (configBase.IntervalTime > 0)
                    Timers++;
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); isCalling = false; }
        }
        //protected virtual bool AutoUpdate(bool isFirst)
        //{
        //    try
        //    {
        //        if (!configBase.IsAutoUpdate)
        //            return false;
        //        string assemblyString = configBase.GetAppSettings("AutoUpdateAssembly", "WcfUpdateService.LiveUpdateClient");
        //        if (isFirst)
        //        {
        //            if (LogUtil.AssemblyInvokeMethod(assemblyString, "UpdateFile", new object[] { configBase.GetAppSettings("appName") }) != null)
        //                return true;
        //        }
        //        var retobj = LogUtil.AssemblyInvokeMethod(assemblyString, "AutoUpdate", new object[] { configBase.GetAppSettings("appName") });
        //        if (retobj != null && Convert.ToBoolean(retobj))
        //            return true;
        //    }
        //    catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        //    return false;
        //}
        /// <summary>
        /// timer触发一次调用
        /// </summary>
        protected virtual void timerCall()
        { }
        /// <summary>
        /// 本次调用结束
        /// </summary>
        protected virtual void endCall()
        { isCalling = false; }
        #endregion

        #region ShowConfigInfo
        /// <summary>
        /// 显示系统配置信息
        /// </summary>
        protected virtual void ShowConfigInfo()
        {            
            LogUtil.Info("- 系统配置信息：");
            LogUtil.Info(string.Format("-- 定时执行间隔：{0}{1}", (ConfigBase.TimeType == 2 ? ConfigBase.IntervalTime / (60 * 60) : (ConfigBase.TimeType == 1 ? ConfigBase.IntervalTime / 60 : ConfigBase.IntervalTime))
                                                     , (ConfigBase.TimeType == 2 ? "小时" : (ConfigBase.TimeType == 1 ? "分钟" : "秒"))));
           //if( ConfigBase.IsAutoUpdate)
           //    LogUtil.Info("-- 是否自动更新(IsAutoUpdate)=" + ConfigBase.IsAutoUpdate);
            LogUtil.Info("-- 服务标识名称(ServiceName)=" + ConfigBase.ServiceName);
            LogUtil.Info("-- 服务显示名称(DisplayName)=" + ConfigBase.DisplayName);
            LogUtil.Info("-- 服 务  说 明(Description)=" + ConfigBase.Description);
            LogUtil.Info("-- 服 务  依 赖(DependedOn) =" + ConfigBase.DependedOn);
        }
        #endregion

        #region WatcherStrart
        protected bool fileChanged = false;
        protected FileSystemWatcher watcher = null;
        protected virtual void WatcherStrart(string filter = "*.dll")
        {
            try
            {
                if (!Convert.ToBoolean(configBase.GetAppSettings("IsFileWatcher", "true")))
                    return;

                if (!Directory.Exists(BaseDirectory))
                {
                    LogUtil.Error("找不到路径：WatcherStrart," + BaseDirectory);
                    return;
                }
                LogUtil.Info("WatcherStrarted path=" + BaseDirectory + ",filter=" + filter);
                watcher = new FileSystemWatcher(BaseDirectory, filter);
                watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime;//| NotifyFilters.FileName | NotifyFilters.CreationTime;
                watcher.EnableRaisingEvents = true;
                watcher.IncludeSubdirectories = false;
                watcher.Changed -= watcher_Changed;
                watcher.Created -= watcher_Changed;
                watcher.Changed += watcher_Changed;
                watcher.Created += watcher_Changed;
            }
            catch (Exception ex) { LogUtil.Error(ex.ToString()); }
        }
        protected virtual void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            try
            {
                LogUtil.Info("有文件更新【" + e.Name + "】" + e.ChangeType);
                fileChanged = true;
            }
            catch (Exception ex) { LogUtil.Error("watcher_Changed," + ex.ToString()); }
        }
        #endregion
    }
}
